#ifndef uart_port_h
#define uart_port_h

#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>

#ifndef NULL
#define NULL ((void*)0)
#endif

<<<<<<< HEAD
#define UART_OBJ_FW_VERSION "2.2.8"
=======
#define UART_OBJ_FW_VERSION "2.2.7"
>>>>>>> 22f544b8ad86c4c784d7594d8b4ac52a567302db

/*--------------------------------------------------用户配置区--------------------------------------------------------------*/


/*
    说明：
    模式可以选择单字节中断，也可以选择dma，也可以都选择
    当DMA无IDLE模式时，需要配置计数器的方向，USE_DMA_RX_CNT_MODE

    USE_UART_TX_RX_MODE_SELECT 该宏是为了使该库可选择 只发送 只接收 或 发送接收 模式，
    默认宏定义不开的情况下，是必须要初始化收发参数的，如果选择只发送，那么初始化时只需要初始化发送参数即可，
    如果选择只接收，那么初始化时只需要初始化接收参数即可，
    收发都选择，那么都需要初始化

*/
<<<<<<< HEAD
#define USE_UART_OBJ_FW_ASSERT        1                              // 是否使用断言辅助调试，0-不使用，1-使用
#define USE_ONE_BYTE_IT_MODE          1                              // 串口单字节中断模式 0-不启用，1-启用
#define USE_DMA_MODE                  1                              // 串口DMA模式
#define USE_DMA_NOT_HAVE_RX_IDLE_MODE 1                              // MCU不支持DMA空闲中断模式情况启用
#define USE_DMA_RX_POSITIVE_CNT       0                              // DMA接收计数器值为正向计数值 0-设定值
#define USE_DMA_RX_NEGATIVE_CNT       1                              // DMA接收计数器值为负向计数值 设定值-0
#define USE_DMA_RX_CNT_MODE           USE_DMA_RX_NEGATIVE_CNT        // DMA接收计数器模式选择
#define USE_UART_TX_BIN_DATA          1                              // 是否启用自定义串口发送二进制数据接口
#define USE_UART_TX_STR_DATA          1                              // 是否启用自定义串口发送字符串数据接口
#define USE_UART_PRINTF               1                              // 是否启用自定义串口printf接口
#define USE_UART_PRINTF_BUF_STATIC    1                              // 是否使用静态缓存区，1-使用，0-不使用
#define USE_STD_LIB                   1                              // 是否使用标准库printf，0-不使用，1-使用
#define USE_STRING_EX_LIB             1                              // 是否使用字符串扩展库(自己写的第三方库)，0-不使用，1-使用
#define USE_INFO_LOG                  1                              // 启用日志0-不启用，1-启用
#define USE_THREAD_SAFE               0                              // 是否使用线程安全模式，0-不使用，1-使用
#define USE_UART_TX_RX_MODE_SELECT    0                              // 是否使用串口发送接收模式选择，0-不使用，1-使用
=======
#define USE_UART_OBJ_FW_ASSERT        1        // 是否使用断言辅助调试，0-不使用，1-使用
#define USE_ONE_BYTE_IT_MODE          1        // 串口单字节中断模式 0-不启用，1-启用
#define USE_DMA_MODE                  1        // 串口DMA模式
#define USE_DMA_NOT_HAVE_RX_IDLE_MODE 1        // MCU不支持DMA空闲中断模式情况启用
#define USE_DMA_RX_POSITIVE_CNT       0        // DMA接收计数器值为正向计数值 0-设定值
#define USE_DMA_RX_NEGATIVE_CNT       1        // DMA接收计数器值为负向计数值 设定值-0
#define USE_DMA_RX_CNT_MODE           USE_DMA_RX_NEGATIVE_CNT        // DMA接收计数器模式选择
#define USE_UART_TX_BIN_DATA          1        // 是否启用自定义串口发送二进制数据接口
#define USE_UART_TX_STR_DATA          1        // 是否启用自定义串口发送字符串数据接口
#define USE_UART_PRINTF               1        // 是否启用自定义串口printf接口
#define USE_UART_PRINTF_BUF_STATIC    1        // 是否使用静态缓存区，1-使用，0-不使用
#define USE_STD_LIB                   1        // 是否使用标准库printf，0-不使用，1-使用
#define USE_STRING_EX_LIB             1        // 是否使用字符串扩展库(自己写的第三方库)，0-不使用，1-使用
#define USE_INFO_LOG                  1        // 启用日志0-不启用，1-启用
#define USE_THREAD_SAFE               0        // 是否使用线程安全模式，0-不使用，1-使用
#define USE_UART_TX_RX_MODE_SELECT    0        // 是否使用串口发送接收模式选择，0-不使用，1-使用
>>>>>>> 22f544b8ad86c4c784d7594d8b4ac52a567302db

// 数值类
#define VALUE_UART_RX_FRAME_BREAK_TIME_MIN 5           // 最小接收帧超时时间 单位ms
#define VALUE_UART_RX_FRAME_BREAK_TIME_MAX 1000        // 最大接收帧超时时间 单位ms
#define VALUE_UART_PRINTF_BUF_SIZE         96          // 自定义串口printf缓存区大小

//预定义常规2次方数值，用于定义串口接收缓冲区使用
typedef enum
{
<<<<<<< HEAD
    UART_FIFO_SIZE_1   = 1,
    UART_FIFO_SIZE_2   = 2,
    UART_FIFO_SIZE_4   = 4,
    UART_FIFO_SIZE_8   = 8,
    UART_FIFO_SIZE_16  = 16,
    UART_FIFO_SIZE_32  = 32,
    UART_FIFO_SIZE_64  = 64,
    UART_FIFO_SIZE_128 = 128,
} power_of_two_num;
=======
	UART_FIFO_SIZE_1 = 1,
	UART_FIFO_SIZE_2 = 2,
	UART_FIFO_SIZE_4 = 4,
	UART_FIFO_SIZE_8 = 8,
	UART_FIFO_SIZE_16 = 16,
	UART_FIFO_SIZE_32 = 32,
	UART_FIFO_SIZE_64 = 64,
	UART_FIFO_SIZE_128 = 128,
}power_of_two_num;
>>>>>>> 22f544b8ad86c4c784d7594d8b4ac52a567302db

/*---------------------------------------------------------------------------------------------------------------------------------*/

/*--------------------------------------------------------------其他第三方库--------------------------------------------------------*/
#if (USE_STRING_EX_LIB == 1)
#include "string_ex.h"
#endif

#if (USE_STD_LIB == 0)
#include "xprintf.h"
#endif
/*-----------------------------------------------------------------------------------------------------------------------------*/

#if (USE_INFO_LOG == 1)
#if (USE_STD_LIB == 1)
#define UART_INFO_LOG printf
#else
#define UART_INFO_LOG xprintf
#endif        // (USE_STD_LIB == 1)
#endif        // USE_INFO_LOG

// 串口框架模式选择
typedef enum
{
    FW_UART_TX_ONLY = 0,
    FW_UART_RX_ONLY,
    FW_UART_TX_RX,
} uart_mode_enum_t;

// 这边使用普通数据类型 考虑结构体的对齐
#define uart_mode_t uint16_t

typedef enum
{
    uart_obj_ok = 0,
    uart_obj_para_err,
    uart_obj_not_init,
    uart_obj_no_rx_it_event,        // 无串口接收中断事件

    // rx fifo
    uart_fifo_wr_full,         // 接收FIFO写满
    uart_fifo_wr_ok,           // 接收FIFO写成功
    uart_fifo_rd_empty,        // 接收FIFO读空
    uart_fifo_rd_ok,           // 接收FIFO读成功

    // uart mode
    uart_obj_mode_tx_only,        // 串口发送模式
    uart_obj_mode_rx_only,        // 串口接收模式
    uart_obj_mode_tx_rx,          // 串口发送接收模式
} uart_obj_sta_t;

typedef void (*def_uart_fifo_rx_start_cb)(uint8_t*, uint16_t);        // 串口接收FIFO启动回调函数
<<<<<<< HEAD
typedef void (*def_uart_fifo_rx_stop_cb)(void);                       // 串口接收FIFO停止回调函数
typedef void (*def_uart_fifo_rx_cb)(uint8_t*, uint16_t);              // 串口接收FIFO数据回调函数
=======
typedef void (*def_uart_fifo_rx_stop_cb)(void);        // 串口接收FIFO停止回调函数
typedef void (*def_uart_fifo_rx_cb)(uint8_t*, uint16_t);        // 串口接收FIFO数据回调函数
>>>>>>> 22f544b8ad86c4c784d7594d8b4ac52a567302db
typedef void (*def_uart_tx_port_cb)(uint8_t*,
                                    uint16_t);        // 串口发送的接口，参数为发送地址，发送长度

// 单字节中断
<<<<<<< HEAD
typedef uint8_t (*def_uart_get_rx_one_byte_cb)(uint8_t*);        // 串口接收一字节的接口，返回值为是否是串口接收中断，形参为数据的指针

// 获取当前DMA接收到的字节数
typedef uint16_t (*def_get_uart_dma_rx_current_cnt_cb)(void);        // 获取当前DMA接收到的字节数,请注意有些获取到的是从配置值递减到零的数值！！！
=======
typedef uint8_t (*def_uart_get_rx_one_byte_cb)(
    uint8_t*);        // 串口接收一字节的接口，返回值为是否是串口接收中断，形参为数据的指针

// 获取当前DMA接收到的字节数
typedef uint16_t (*def_get_uart_dma_rx_current_cnt_cb)(
    void);        // 获取当前DMA接收到的字节数,请注意有些获取到的是从配置值递减到零的数值！！！
>>>>>>> 22f544b8ad86c4c784d7594d8b4ac52a567302db

// 线程安全模式
typedef void (*def_tx_lock_cb)(void);          // 串口发送锁
typedef void (*def_tx_unlock_cb)(void);        // 串口发送解锁

// fifo 接收管理需要的变量
typedef struct
{
    uint16_t rx_fifo_data_len;        // 记录每包数据的长度
} rx_fifo_manage_t;

// 串口初始化结构体
typedef struct
{
    // 线程安全模式
#if (USE_THREAD_SAFE == 1)
    def_tx_lock_cb   tx_lock_cb;          // 串口发送锁
    def_tx_unlock_cb tx_unlock_cb;        // 串口发送解锁
#endif

    // 发送暂时不使用fifo
    uint8_t*            tx_buf_addr;            // 发送缓冲区
    def_uart_tx_port_cb uart_tx_port_cb;        // 发送接口
    uint16_t            tx_buf_size;            // 发送缓冲区大小

    // 接收需要初始化的参数
    uint16_t rx_time_out_set;                // 接收超时时间，有idle中断这种参数忽略
    uint8_t* rx_fifo_buf_base_addr;          // 接收缓冲区基地址
    uint16_t rx_fifo_buf_size_single;        // 单个缓冲区大小
<<<<<<< HEAD
    uint16_t rx_fifo_buf_size_total;         // 接收缓冲区总大小 = 单个缓冲区大小 * FIFO深度
    uint16_t rx_fifo_deep;                   // 接收FIFO深度

#if (USE_UART_TX_RX_MODE_SELECT == 1)
    uart_mode_t uart_mode;        // 串口模式
#endif
    rx_fifo_manage_t*   rx_fifo_manage;         // 接收fifo管理结构体 （由于fifo 深度为动态确定，只能为用户传入）
=======
    uint16_t rx_fifo_buf_size_total;        // 接收缓冲区总大小 = 单个缓冲区大小 * FIFO深度
    uint16_t rx_fifo_deep;                  // 接收FIFO深度
                                            // 串口模式 （在此处是为了内存对齐）
#if (USE_UART_TX_RX_MODE_SELECT == 1)
    uart_mode_t uart_mode;        // 串口模式
#endif
    rx_fifo_manage_t*
                        rx_fifo_manage;        // 接收fifo管理结构体 （由于fifo 深度为动态确定，只能为用户传入）
>>>>>>> 22f544b8ad86c4c784d7594d8b4ac52a567302db
    def_uart_fifo_rx_cb uart_fifo_rx_cb;        // 串口接收FIFO数据回调函数

    // 串口接收启停函数
    def_uart_fifo_rx_stop_cb  uart_fifo_rx_stop_cb;         // 串口接收FIFO停止回调函数
    def_uart_fifo_rx_start_cb uart_fifo_rx_start_cb;        // 串口接收FIFO启动回调函数

    // 单字节中断相关参数
#if (USE_ONE_BYTE_IT_MODE == 1)
    def_uart_get_rx_one_byte_cb uart_get_rx_one_byte_cb;
#endif
    // dma模式相关参数
#if (USE_DMA_MODE == 1 && USE_DMA_NOT_HAVE_RX_IDLE_MODE == 1)
    def_get_uart_dma_rx_current_cnt_cb get_uart_dma_rx_current_cnt_cb;
#endif
} uart_init_t;

typedef union
{
    uint8_t value;
    struct
    {
        uint8_t init_mode_it : 1;         // 单字节中断模式是否初始化完成
        uint8_t init_mode_dma : 1;        // dma模式是否初始化完成
    } bits;
} uart_init_flag_t;

/*--------------------------------串口底层------------------------------*/
// 串口对象结构体
typedef struct
{
    // 初始化参数
    uart_init_t init;

    // 非初始化需要传入的参数
    uint8_t* rx_fifo_buf_cur_addr;        // 当前接收缓冲区地址
    uint16_t rx_fifo_wr_cnt;              // 每写入一包数据，fifo_write_cnt加一
    uint16_t rx_fifo_rd_cnt;              // 每读取一包数据，fifo_read_cnt加一
    uint16_t rx_fifo_data_volume;         // 接收FIFO数据量

    // 接收超时判定相关参数
    uint16_t rx_cnt_now;         // 当前接收到的数据长度
    uint16_t rx_cnt_bef;         // 上一次接收到的数据长度
    uint16_t rx_time_out;        // 接收超时时间

    uint16_t tx_len;        // 发送长度（发送使用）

    uint8_t rx_cache_one_byte;        // 接收缓存器单字节中断接收时的数据

    uart_init_flag_t init_flag;        // 初始化标志位
} uart_obj_t;

/*------------------------------------------------------断言---------------------------------------------------------*/
void uart_obj_fw_assert(char* file, uint32_t line);
<<<<<<< HEAD
#define UART_OBJ_FW_ASSERT(cond)                             \
    do                                                       \
    {                                                        \
        if (!(cond)) uart_obj_fw_assert(__FILE__, __LINE__); \
    } while (0)

/*----------------------------------------------单字节中断模式接口----------------------------------------------------*/
=======
#define UART_OBJ_FW_ASSERT(cond) do { if ((cond)) uart_obj_fw_assert(__FILE__, __LINE__); } while(0)

/*----------------------------------------------单字节中断
 * 模式接口----------------------------------------------------*/
>>>>>>> 22f544b8ad86c4c784d7594d8b4ac52a567302db
#if (USE_ONE_BYTE_IT_MODE == 1)
// 单字节初始化串口
uart_obj_sta_t uart_obj_it_init(uart_obj_t* obj, const uart_init_t* init_param);
// 串口断帧
uart_obj_sta_t uart_obj_it_rx_frame_break(uart_obj_t* obj);
// 串口单字节中断接收
uart_obj_sta_t uart_obj_it_rx_byte_irq(uart_obj_t* obj);
#endif

<<<<<<< HEAD
/*----------------------------------------------dma模式接口------------------------------------------------------------*/
=======
/*----------------------------------------------dma
 * 模式接口------------------------------------------------------------*/
>>>>>>> 22f544b8ad86c4c784d7594d8b4ac52a567302db
#if (USE_DMA_MODE == 1)
// dma 初始化
uart_obj_sta_t uart_obj_dma_init(uart_obj_t* obj, const uart_init_t* init_param);
#if (USE_DMA_NOT_HAVE_RX_IDLE_MODE == 1)
// dma 超时断帧
uart_obj_sta_t uart_obj_dma_rx_frame_break(uart_obj_t* obj);
#else
// dma idle中断
uart_obj_sta_t uart_obj_dma_rx_idle_finish(uart_obj_t* obj, uint16_t len);
#endif        // (USE_DMA_NOT_HAVE_RX_IDLE_MODE == 1)
#endif        // (USE_DMA_MODE == 1)

/*----------------------------------------------串口写数据接口------------------------------------------------------------*/
#if (USE_UART_TX_BIN_DATA == 1)
// 串口发送二进制数据
uart_obj_sta_t uart_obj_tx_bin_data(uart_obj_t* obj, const void* udata, uint16_t len);
#endif

#if (USE_UART_TX_STR_DATA == 1)
// 串口发送字符串数据
uart_obj_sta_t uart_obj_tx_str_data(uart_obj_t* obj, const char* str);
#endif

#if (USE_UART_PRINTF == 1)
// 串口打印
uart_obj_sta_t uart_obj_printf(uart_obj_t* obj, const char* fmt, ...);
#endif
/*----------------------------------------------串口读数据接口------------------------------------------------------------*/
// 接收FIFO读取数据
uart_obj_sta_t uart_obj_rx_fifo_read(uart_obj_t* obj);

/*-----------------------------------------------小功能------------------------------------------------------------------*/

// 设置接收帧超时时间
uart_obj_sta_t uart_obj_set_rx_frame_break_time(uart_obj_t* obj, uint16_t ms);

// 获取接收帧超时时间
uint16_t uart_obj_get_rx_frame_break_time(uart_obj_t* obj);

/*-----------------------------------------------API 重定义---------------------------------------------------------------*/
// 用户可以根据自己的需求重命名一些接口
// 重命名读写接口
#define uart_obj_read  uart_obj_rx_fifo_read        // 注意读数据是回调处理
#define uart_obj_write uart_obj_tx_bin_data

/*------------------------------------------用户自定义库函数---------------------------------------------------------*/
void uart_obj_std_lib_redefine(void);
#endif
